package com.boyon.web.servlet.tomcat;

import java.io.IOException;

import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Session;
import org.apache.catalina.SessionIdGenerator;
import org.apache.catalina.session.ManagerBase;
import org.apache.catalina.util.SessionIdGeneratorBase;
import org.apache.catalina.util.StandardSessionIdGenerator;

import com.boyon.common.tools.ObjectTool;
import com.boyon.common.tools.StringTool;
import com.boyon.redis.adapter.JedisAdapter;
import com.boyon.redis.wrap.JedisWrap;

import lombok.extern.slf4j.Slf4j;

/**
 * ClassName:TomcatManager <br/>
 * Function: tomcat管理类. <br/>
 * Date: 2018年3月26日 下午8:57:47 <br/>
 * 
 * @author sunshulin
 * @version
 * @since JDK 1.8
 * @see
 */
@Slf4j
public class TomcatManager extends ManagerBase {

	private JedisAdapter jedisAdapter;

	public static final int database = 10;

	public final String SESSION_ID = "sessionId";

	/**
	 * Creates a new instance of TomcatManager.
	 * 
	 * @param jedisAdapter
	 */
	public TomcatManager(JedisAdapter jedisAdapter) {
		super();
		this.jedisAdapter = jedisAdapter;
	}

	/**
	 * session保存redis中.
	 * 
	 * @see org.apache.catalina.Manager#add(org.apache.catalina.Session)
	 */
	public void add(Session session) {
		log.debug("添加session,此处更改成redis{}", session.getId());
		JedisWrap jedisWrap = jedisAdapter.getResource();
		try {
			jedisWrap.selectDatabase(database);
			byte[] sessionId = session.getId().getBytes();
			jedisWrap.hset(sessionId, SESSION_ID.getBytes(),
					ObjectTool.toByteArray(session));
			jedisWrap.expire(sessionId, 3600);
		} finally {
			jedisWrap.release();
		}
	}

	/**
	 * sessionId创建session.
	 * 
	 * @see org.apache.catalina.Manager#createSession(java.lang.String)
	 */
	public Session createSession(String sessionId) {
		log.debug("创建session={}", sessionId);
		Session session = createEmptySession();
		session.setNew(true);
		session.setValid(true);
		session.setCreationTime(System.currentTimeMillis());
		session.setMaxInactiveInterval(3600);
		String id = sessionId;
		if (id == null) {
			id = generateSessionId();
		}
		session.setId(id);
		// TODO 此处加入session事件监控
		return session;
	}

	/**
	 * id查询session.
	 * 
	 * @see org.apache.catalina.Manager#findSession(java.lang.String)
	 */
	public Session findSession(String id) throws IOException {
		log.debug("session id 查找session={}", id);
		Session session = null;
		if (StringTool.isNotNull(id)) {
			JedisWrap jedisWrap = jedisAdapter.getResource();
			try {
				jedisWrap.selectDatabase(database);
				byte[] sessionId = id.getBytes();
				Boolean exist = jedisWrap.exists(sessionId);
				if (ObjectTool.isNotNull(exist) && exist) {
					byte[] bytes = jedisWrap.hget(sessionId,
							SESSION_ID.getBytes());
					if (ObjectTool.isNotNull(bytes)) {
						session = (Session) ObjectTool.toObject(bytes);
					}
				}
			} finally {
				jedisWrap.release();
			}
		}
		if (!ObjectTool.isNotNull(session)) {
			session = createSession(id);
			add(session);
		}
		session.setManager(this);
		return session;
	}

	/**
	 * 获取所有的session.
	 * 
	 * @see org.apache.catalina.Manager#findSessions()
	 */
	public Session[] findSessions() {
		log.debug("获取所有的session");
		return null;
	}

	/**
	 * TODO 简单描述该方法的实现功能（可选）.
	 * 
	 * @see org.apache.catalina.Manager#load()
	 */
	public void load() throws ClassNotFoundException, IOException {

	}

	/**
	 * 删除session.
	 * 
	 * @see org.apache.catalina.Manager#remove(org.apache.catalina.Session,
	 *      boolean)
	 */
	public void remove(Session session, boolean update) {
		log.debug("删除session");
		JedisWrap jedisWrap = jedisAdapter.getResource();
		try {
			jedisWrap.selectDatabase(database);
			byte[] sessionId = session.getId().getBytes();
			jedisWrap.delete(sessionId);
		} finally {
			jedisWrap.release();
		}
	}

	/**
	 * TODO 简单描述该方法的实现功能（可选）.
	 * 
	 * @see org.apache.catalina.Manager#unload()
	 */
	public void unload() throws IOException {

	}

	/**
	 * session时间.
	 * 
	 * @see org.apache.catalina.Manager#backgroundProcess()
	 */
	public void backgroundProcess() {
		log.debug("session process");
	}

	/**
	 * .
	 * 
	 * @see org.apache.catalina.Manager#willAttributeDistribute(java.lang.String,
	 *      java.lang.Object)
	 */
	public boolean willAttributeDistribute(String name, Object value) {
		log.debug("willAttributeDistribute");
		return false;
	}

	/**
	 * tomcat startInternal.
	 * 
	 * @see org.apache.catalina.util.LifecycleBase#startInternal()
	 */
	protected void startInternal() throws LifecycleException {
		log.debug("tomcat manager startInternal");
		super.startInternal();
		SessionIdGenerator sessionIdGenerator = new StandardSessionIdGenerator();
		setSessionIdGenerator(sessionIdGenerator);
		sessionIdGenerator.setJvmRoute(getJvmRoute());
		if (sessionIdGenerator instanceof SessionIdGeneratorBase) {
			SessionIdGeneratorBase sig = (SessionIdGeneratorBase) sessionIdGenerator;
			sig.setSecureRandomAlgorithm(getSecureRandomAlgorithm());
			sig.setSecureRandomClass(getSecureRandomClass());
			sig.setSecureRandomProvider(getSecureRandomProvider());
		}
		if (sessionIdGenerator instanceof Lifecycle) {
			((Lifecycle) sessionIdGenerator).start();
		} else {
			sessionIdGenerator.generateSessionId();
		}
		setState(LifecycleState.STARTING);
	}

	/**
	 * .
	 * 
	 * @see org.apache.catalina.util.LifecycleBase#stopInternal()
	 */
	protected void stopInternal() throws LifecycleException {
		setState(LifecycleState.STOPPING);
		super.stopInternal();
	}

	/**
	 * 创建session
	 * 
	 * @see org.apache.catalina.session.ManagerBase#createEmptySession()
	 */
	public Session createEmptySession() {
		return new TomcatSession(this);
	}

	/**
	 * JedisWrap.
	 * 
	 * @return the JedisWrap
	 * @since JDK 1.8
	 */
	public JedisWrap getJedisWrap() {
		return jedisAdapter.getResource();
	}
}
